﻿using Entity.BaseEntitys;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions;
using ShardingCore.Sharding.PaginationConfigurations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Entity.BaseSplit
{

    /// <summary>
    /// Since the entity depots routing constraints
    /// </summary>
    public class BaseSplitDataSourceRoute<T,Key> : AbstractShardingOperatorVirtualDataSourceRoute<T, string> where T :  Entity<Key>
    {
        private readonly List<string> _dataSources = SplitAreaSource.GetAllSource().ToList();

        public override string ShardingKeyToDataSourceName(object shardingKey)
         => shardingKey?.ToString() ?? string.Empty;

        public override bool? EnableRouteParseCompileCache => true;

        public override List<string> GetAllDataSourceNames()
         => _dataSources;
         

        public override bool AddDataSourceName(string dataSourceName)
        {
            if (_dataSources.Any(o => o == dataSourceName))
                return false;
            _dataSources.Add(dataSourceName);
            return true;
        }

        public override Expression<Func<string, bool>> GetRouteToFilter(string shardingKey, ShardingOperatorEnum shardingOperator)
        {

            var t = ShardingKeyToDataSourceName(shardingKey);
            switch (shardingOperator)
            {
                case ShardingOperatorEnum.Equal: return tail => tail == t;
                default:
                    {
                        return tail => true;
                    }
            }
        }

        public override void Configure(EntityMetadataDataSourceBuilder<T> builder)
         => builder.ShardingProperty(o => o.SplitArea);
    }


    public class SplitDataSourcePaginationConfiguration<T, Key> : IPaginationConfiguration<T> where T : Entity<Key>
    {
        public void Configure(PaginationBuilder<T> builder)
        {
            builder.PaginationSequence(o => o.Id)
                .UseRouteComparer(Comparer<string>.Default)
                .UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch).UseAppendIfOrderNone(10);

            builder.ConfigReverseShardingPage(1d, 10000L);
        }
    }
}
